/*
 * @Description: 
 * @FilePath: /STM32F103/USER/bsp/gpio.c
 * @Author: Wei Zhou
 * @Github: https://github.com/zromyk
 * @Date: 2021-05-12 20:17:46
 * @LastEditors: Wei Zhou
 * @LastEditTime: 2021-05-12 22:01:36
 * @Copyright: Copyright © 2017 muyiro. All rights reserved.
 */

#include "gpio.h"
#include "rcc.h"

static GPIO_TypeDef* GPIOx_BASE[] = 
{
    GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG
};

void gpio_out_init(PIN_Dev pin, uint16_t bit)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_TypeDef* GPIOx     = GPIOx_BASE[getGPIO(pin)];
    uint16_t GPIO_Pin       = (((uint16_t)GPIO_Pin_0) << getPIN(pin));
    uint32_t RCC_APB2Periph = (((uint32_t)RCC_APB2Periph_GPIOA) << getGPIO(pin));

    RCC_APB2PeriphClockCmd(RCC_APB2Periph, ENABLE);
    
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOx, &GPIO_InitStruct);

    if (bit) { GPIO_SetBits  (GPIOx, GPIO_Pin); }
    else     { GPIO_ResetBits(GPIOx, GPIO_Pin); }
}

void gpio_in_init(PIN_Dev pin, GPIOPuPd_TypeDef PuPd)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_TypeDef* GPIOx     = GPIOx_BASE[getGPIO(pin)];
    uint16_t GPIO_Pin       = (((uint16_t)GPIO_Pin_0) << getPIN(pin));
    uint32_t RCC_APB2Periph = (((uint32_t)RCC_APB2Periph_GPIOA) << getGPIO(pin));

    RCC_APB2PeriphClockCmd(RCC_APB2Periph, ENABLE);
    
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    switch (PuPd) {
        case GPIO_PuPd_NOPULL:  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
        case GPIO_PuPd_UP:      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; break;
        case GPIO_PuPd_DOWN:    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; break;
    }
    GPIO_Init(GPIOx, &GPIO_InitStruct);
}

void gpio_af_init(PIN_Dev pin)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_TypeDef* GPIOx     = GPIOx_BASE[getGPIO(pin)];
    uint16_t GPIO_Pin       = (((uint16_t)GPIO_Pin_0) << getPIN(pin));
    uint32_t RCC_APB2Periph = (((uint32_t)RCC_APB2Periph_GPIOA) << getGPIO(pin));
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph, ENABLE);
    
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOx, &GPIO_InitStruct);
}

void gpio_write(PIN_Dev pin, uint16_t bit)
{
    GPIO_TypeDef* GPIOx     = GPIOx_BASE[getGPIO(pin)];
    uint16_t GPIO_Pin       = (((uint16_t)GPIO_Pin_0) << getPIN(pin));
    
    if (bit) { GPIO_SetBits  (GPIOx, GPIO_Pin); }
    else     { GPIO_ResetBits(GPIOx, GPIO_Pin); }
}

uint8_t gpio_read(PIN_Dev pin)
{
    GPIO_TypeDef* GPIOx     = GPIOx_BASE[getGPIO(pin)];
    uint16_t GPIO_Pin       = (((uint16_t)GPIO_Pin_0) << getPIN(pin));
    
    return GPIO_ReadInputDataBit (GPIOx, GPIO_Pin);
}

